//配置路由的地方
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from '@/router/router'
//引入store
import store from '@/store/index'

//查用插件
Vue.use(VueRouter)

//配置路由
let router = new VueRouter({
  model: 'history',
  routes,
  //滚动行为
  scrollBehavior(to, from, savedPosition) {
    // 始终滚动到顶部
    return { y: 0 }
  },
})

//全局守卫：前置守卫（在路由跳转之间进行判断）
router.beforeEach(async (to, from, next) => {
  //to：获取到要跳转到的路由信息
  //from:获取到从那个路由跳转过来的信息
  //next：next() 放行  next(path),放行到path
  //查看用户登陆token
  let token = store.state.user.token
  let name = store.state.user.userInfo.name
  if (token) {
    //如果已经登陆，不再去登陆页了
    if (to.path == '/login' || to.path == '/register') {
      next('home')
    } else {
      if (name) {
        next()
      } else {
        //登陆了且没有用户信息
        //在路由跳转之前获取用户信息且放行
        try {
          await store.dispatch('user/getUserInfo')
          next()
        } catch (error) {
          console.log(error)
          //token失效从新登录
          await store.dispatch('user/logOut')
          next('/login')
        }
      }
    }
  } else {
    //未登录  放行
    next()
    console.log('未登录')
  }
})

export default router

/**
 *  解决Uncaught (in promise) NavigationDuplicated报错，因为push实际调用了promise方法，需要两个回调方法
    低版本的cli中的push没有这两个参数，就重写push方法处理一下这个异常
    重写push与replace方法  正常写法
    call和apply都可以调用一次函数，篡改一次上下文
    call和apply的区别，call传递参数用逗号隔开，apply用数组
    */
const originalPush = VueRouter.prototype.push
const originalReplace = VueRouter.prototype.replace

VueRouter.prototype.push = function push(location, req, res) {
  if (req && res) {
    originalPush.call(this, location, req, res)
  } else {
    originalPush.call(
      this,
      location,
      () => {},
      () => {}
    )
  }
}
VueRouter.prototype.replace = function replace(location, req, res) {
  if (req && res) {
    originalReplace.call(this, location, req, res)
  } else {
    originalReplace.call(
      this,
      location,
      () => {},
      () => {}
    )
  }
}

/* 
捕获写法 
VueRouter.prototype.push = function push(location) {
   return originalPush.call(this, location).catch(err => err)
} */
